package 困难.分类讨论;

import java.util.HashSet;
import java.util.Set;

/**
 * 如果一个密码满足下述所有条件，则认为这个密码是强密码：
 * 由至少 6 个，至多 20 个字符组成。
 * 至少包含 一个小写 字母，一个大写 字母，和 一个数字 。
 * 同一字符 不能 连续出现三次 (比如 "...aaa..." 是不允许的, 但是 "...aa...a..." 如果满足其他条件也可以算是强密码)。
 * 给你一个字符串 password ，返回 将 password 修改到满足强密码条件需要的最少修改步数。如果 password 已经是强密码，则返回 0 。
 * 在一步修改操作中，你可以：
 * 插入一个字符到 password ，
 * 从 password 中删除一个字符，或
 * 用另一个字符来替换 password 中的某个字符。
 * <p>
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/strong-password-checker
 */
public class 强密码检验器_420 {

    public static void main(String[] args) {

        System.out.println(strongPasswordChecker("aaa111"));

    }

    /**
     * 分类讨论：
     * 如果密码长度 <6  那么至少使用 6-len 次修改
     * 密码长度 >=6 && <=20  那么优先使用 修改 ，因为 修改 可以代替 一次增加和一次删除
     * 密码长度 >20  那么至少使用 len-20 次删除
     * <p>
     * 因为密码可以包含 大写字母小写字母和数字，那么有 26+26+10 种不同的字符，我们可以
     * 不用考虑修改什么值，或者增加什么值
     * <p>
     * 只要 需要修改或者增加次数 >=3 就可能不用考虑 一个小写 字母，一个大写 字母，和 一个数字 的条件
     * 0  2
     * aab
     *
     * @param password
     * @return
     */
    // TODO 未考虑 aaaaa 其实只需要一次修改操作和一次新增操作
    public static int strongPasswordChecker(String password) {
        Set<Integer> set = new HashSet<>();
        int len = password.length();
        for (int i = 0; i < len; i++) {
            if (Character.isUpperCase(password.charAt(i))) {
                set.add(1);
            } else if (Character.isLowerCase(password.charAt(i))) {
                set.add(2);
            } else if (Character.isDigit(password.charAt(i))) {
                set.add(3);
            }
        }
        int existCharCount = set.size();
        int repeatCount = 0;
        int left = 0;
        while (left < len) {
            int right = left;
            while (right < len && password.charAt(right) == password.charAt(left)) {
                right++;
            }
            if (right - left >= 3) {
                repeatCount += right - left - 2;  //最多连续3个字符，留下2个
            }
            left = right;
        }

        if (len < 6) {
            if (repeatCount + 6 - len >= 3) {
                return repeatCount + 6 - len;
            } else {  // 只有当密码长度为5，且没有重复字符，只需要增加1个字符
                return Math.max(1, 3 - existCharCount);  // 需要3-existCharCount次修改
            }
        } else if (len > 20) {
            // 正好需要删除 len-20 个字符，优先删除重复的字符，
            // 剩下的重复字符需要修改，重复修改次数和大小写数字最少修改的次数取相对大的
            return len - 20 + (Math.max(repeatCount - (len - 20), 3 - existCharCount));
//            if (repeatCount - (len - 20) >= 3) {  //需要修改次数 >=3
//                return repeatCount;
//            } else if (repeatCount - (len - 20) < 0) {
//                // 删除 len-20 次，此时已经没有重复字符
//                return len - 20 + 3 - existCharCount;
//            } else {  // 22 4  剩下2个重复字符，如果1
//
//            }

        } else {
            return Math.max(repeatCount, 3 - existCharCount);
        }
    }

}
